import multiprocessing
import os
import time

"""
多进程的设计:
    进程控制

    terminate(self):关闭进程
    is_alive(self):是否存活
    join(self,timeout):加入队列强制执行
    p.is_alive(): 判断子线程p1是否存活
    p.terminate(): 强制结束
    p.Process(daemon=true): 守护进程,主线程开启同时他也开启,主线程结束他也结束
    pid = os.fork() # 创建子进程 只支持linux  windows会报错:Has no attribute fork  
    {pid<0创建失败,pid=0子进程获取数据,pid>0父进程获取数据 }
    psutil :进程工具,pip install psutil 

    # join()
    所有的进程通过start()方法启动,而后多个进程进入到阻塞队列,这时候某一个进程是不可能强占cpu的
    如果这个时候有一个进程必须要现在执行,那就要使用join()
    
# 进程池
        多进程可以提高程序运行效率,但是传统的的多进程模式只适合并发并不多的情况:成百上千的并发进程就不适合使用了,
    会造成资源过多的消耗,导致资源不足的问题,从而降低了系统性能,所以要提高资源的利用率,以及进程的可复用性
    
    
# 管道
        为什么使用管道?
        进程和进程之间不能直接通讯,需要用管道连接两个进程才能通讯
        
# 进程队列(Queue)
    为什么使用对列?(使用场景)
    相当于是一个缓冲区,生产出来的数据,先存到队列(queue)中,然后消费进程从队列中(queue)取出数据
    从而实现进程的数据交互
"""

# 生产者
def put_worker(queue):
    for i in range(5):
        print("进程id[{}]   进程name[{}]".format(multiprocessing.current_process().pid,
                                             multiprocessing.current_process().name))
        queue.put("item={}".format(i))
        time.sleep(1)

# 消费者
def get_worker(queue):
    while 1:
        try:
            print('进程id[{}]   进程name[{}]  消费数据[{}]'.format(
                            multiprocessing.current_process().pid,
                            multiprocessing.current_process().name,
                            # block=True 表示阻塞,timeout后才会跑出异常   false表示不阻塞,没有数据,或者已经满了跑出异常
                            queue.get(block=True,timeout=2)))
        except:
            print('等待生产......')


def main():
    queue = multiprocessing.Queue()
    put_p = multiprocessing.Process(target=put_worker,args=(queue,),name='生产者进程')
    get_p = multiprocessing.Process(target=get_worker,args=(queue,),name='消费者进程')
    put_p.start()
    get_p.start()
    put_p.join()
    get_p.join()

if __name__ == '__main__':
    main()